package com.orifine.orm;

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

import com.orifine.orm.type.Null;

public class TypeManager {
	private static final Map<Class<?>, Type> typeMappers = new HashMap<Class<?>, Type>();

	public static void register(Class<?> dataClass, Type dataType) {
		typeMappers.put(dataClass, dataType);
	}
	
	public static void register(Class<?> dataClass, Class<? extends Type> typeClass){
		try {
			typeMappers.put(dataClass, typeClass.newInstance());
		} catch (InstantiationException e) {
			throw new RuntimeException(e.getMessage(), e.fillInStackTrace());
		} catch (IllegalAccessException e) {
			throw new RuntimeException(e.getMessage(), e.fillInStackTrace());
		}
	}

	public static Type getType(Class<?> dataClass) {
		Type type = typeMappers.get(dataClass);
		if(type != null){
			return type;
		} else if(Type.class.isAssignableFrom(dataClass)){
			try {
				type = (Type) dataClass.newInstance();
			} catch (InstantiationException e) {
				throw new RuntimeException(e.getMessage(), e.fillInStackTrace());
			} catch (IllegalAccessException e) {
				throw new RuntimeException(e.getMessage(), e.fillInStackTrace());
			}
			register(dataClass, type);
		}
		return type;
	}
	
	public static Type getType(Object typeObject) {
		if(typeObject == null){
			return new Null();
		} else if(typeObject instanceof Type){
			return (Type)typeObject;
		} else {
			Type type = getType(typeObject.getClass());
			if(type != null){
				try {
					return type.getClass().getConstructor(typeObject.getClass()).newInstance(typeObject);
				} catch (IllegalArgumentException e) {
					throw new RuntimeException(e.getMessage(), e.fillInStackTrace());
				} catch (SecurityException e) {
					throw new RuntimeException(e.getMessage(), e.fillInStackTrace());
				} catch (InstantiationException e) {
					throw new RuntimeException(e.getMessage(), e.fillInStackTrace());
				} catch (IllegalAccessException e) {
					throw new RuntimeException(e.getMessage(), e.fillInStackTrace());
				} catch (InvocationTargetException e) {
					throw new RuntimeException(e.getMessage(), e.fillInStackTrace());
				} catch (NoSuchMethodException e) {
					throw new RuntimeException(e.getMessage(), e.fillInStackTrace());
				}
			} else {
				throw new RuntimeException(typeObject.getClass() +"的类型不属于Type类型也不是TypeManager已注册的类型");
			}
		}
	}
}
